package au.com.langdale.gwt.client.ui;

import au.com.langdale.gwt.client.model.ModelListener;
import au.com.langdale.gwt.client.remote.EditManager;
import au.com.langdale.gwt.client.remote.RemoteList;

import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * A user interface for controlling a RemoteList.  Buttons
 * are provided to move to the next, previous and first page
 * of the list.  A status area shows the position of the list.<p>
 * 
 * If an EditManager is provided, the controls are disabled 
 * when there are pending edits.<p>
 * 
 * @author adv
 *
 */
public class NavBar extends Composite implements ModelListener {

	private final DockPanel bar = new DockPanel();
	private final HTML status = new HTML();
	private final Button gotoFirst = new Button("&lt;&lt;");
	private final Button gotoNext = new Button("&gt;");
	private final Button gotoPrev = new Button("&lt;");
	private RemoteList source;
	private EditManager manager;

	public NavBar() {
		initWidget(bar);
		bar.setStyleName("navbar");
		status.setStyleName("status");

		HorizontalPanel buttons = new HorizontalPanel();
		buttons.add(gotoFirst);
		buttons.add(gotoPrev);
		buttons.add(gotoNext);
		bar.add(buttons, DockPanel.EAST);
		bar.setCellHorizontalAlignment(buttons, DockPanel.ALIGN_RIGHT);
		bar.add(status, DockPanel.CENTER);
		bar.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
		bar.setCellHorizontalAlignment(status, HasAlignment.ALIGN_RIGHT);
		bar.setCellVerticalAlignment(status, HasAlignment.ALIGN_MIDDLE);
		bar.setCellWidth(status, "100%");
	}

	private void wireToSource() {
		gotoFirst.addClickListener(new ClickListener(){
			public void onClick(Widget sender) {
				source.first();
			}});
		gotoPrev.addClickListener(new ClickListener(){
			public void onClick(Widget sender) {
				source.prev();
			}});
		gotoNext.addClickListener(new ClickListener(){
			public void onClick(Widget sender) {
				source.next();
			}});
	}

	public RemoteList getSource() {
		return source;
	}

	public void setSource(RemoteList remoteList) {
		if( source == null)
			wireToSource(); // source will be initialised
		else
			source.removeModelListener(this);

		source = remoteList;
		source.addModelListener(this);
		onChange(source);
	}

	public EditManager getEditManager() {
		return manager;
	}
	
	public void setEditManager(EditManager editManager) {
		if( manager != null)
			manager.removeModelListener(this);
		manager = editManager;
		manager.addModelListener(this);
		onChange(manager);
	}

	public void onChange(Object container) {
		int fillCount = source.size();
		int startRow = source.getFirst();
		boolean hasUpdates = manager != null && manager.hasUpdates();
		boolean pending = source.getPending() > 0;
		
		if( fillCount > 0)
			status.setText((startRow + 1) + " - " + (startRow + fillCount));
		else if(fillCount == 0)
			status.setText("No more data.");
		else
			status.setText("Fetching ...");
		
		if( ! pending && ! hasUpdates) {
			gotoFirst.setEnabled(startRow > 0);
			gotoPrev.setEnabled(startRow > 0);
			gotoNext.setEnabled(source.hasMore());
		}
		else {
			gotoFirst.setEnabled(false);
			gotoPrev.setEnabled(false);
			gotoNext.setEnabled(false);
		}
	}

	public void onContentsChange(Object container) {
		// no effect
	}

	public void onModelChange(Object model) {
		// no effect
	}

	public void onCommit(Object container) {
		// no effect
	}
}